package dao;

import model.Goods;
import util.*;

import java.math.BigInteger;
import java.sql.SQLException;
import java.util.List;

public class GoodsManager implements GoodsManagement {
    @Override
    public Long register(Goods goods) {

        if(goods == null || Common.isStringEmpty(goods.getG_name())  || goods.getSt_id() == null ||  goods.getG_price() == null  ||
            Common.isStringEmpty(goods.getG_barcode())  ||  Common.isStringEmpty(goods.getG_status())) return null;

        String sql = "insert into t_goods(sql_args) values(sql_values)";
        StringBuilder sql_args = new StringBuilder("g_id, g_name, st_id, g_price");
        StringBuilder sql_values = new StringBuilder("null, ?, ?");
        ArgsList<Object> args = new ArgsList<>();

        args.add(goods.getG_name());
        args.add(goods.getSt_id());
        args.add(goods.getG_price());

        if(goods.getG_vip_price() != null){
            sql_args.append(", g_vip_price");
            sql_values.append(", ?");
            args.add(goods.getG_vip_price());
        }
        if(!Common.isStringEmpty(goods.getG_descript())){
            sql_args.append(", g_descript");
            sql_values.append(", ?");
            args.add(goods.getG_descript());
        }
        if(!Common.isStringEmpty(goods.getG_pic_address())){
            sql_args.append(", g_pic_address");
            sql_values.append(", ?");
            args.add(goods.getG_pic_address());
        }

        sql_args.append(", g_barcode");
        sql_values.append(", ?");
        args.add(goods.getG_barcode());

        sql_args.append(", g_count");
        sql_values.append(", ?");

        if(goods.getG_count() != null){
            args.add(goods.getG_count());
        } else args.add(0L);

        if(goods.getG_slife() != null){
            sql_args.append(", g_slife");
            sql_values.append(", ?");
            args.add(goods.getG_slife());
        }
        if(goods.getG_score() != null){
            sql_args.append(", g_score");
            sql_values.append(", ?");
            args.add(goods.getG_score());
        }

        sql_args.append(", g_status");
        sql_values.append(", ?");
        args.add(goods.getG_status());

        Object result = null;
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            result = conn.updateForGeneratedKey(args, "insert into t_goods(" + sql_args + ") values(" + sql_values + ")");
            JDBCFactory.returnBack(conn);
            return result == null? null: ((BigInteger)result).longValue();
        } catch(SQLException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    /**
     * 删除商品，暂不支持
     * @param goods 要删除的商品种类
     * @return      删除商品种类的数量
     */
    @Override
    public int delete(Goods goods) {

        //如果有未完成的订单则阻止删除
        //一般来说要先下架商品，等待订单全部完成后方可删除商品
        //从用户购物车t_usergoods中清除该商品
        //从用户收藏表t_userfavgood中清除该商品
        //从商品类别关系表t_goodsoftype中清除该商品的记录
        //从商品打折表t_gsale中清除该商品的记录
        //从店铺商品表t_storegoods中清除该商品的记录
        //从订单记录表t_orders中清除该商品的记录(或将其指向“已删除商品”的id)
        return 0;
    }

    /**
     * 修改商品信息(可批量修改)
     * @param goods 需要修改的商品，设为null则全表更新。设为null的字段则任意匹配
     * @param desti 需要修改的结果，不可为null，设为null的字读不更新
     * @return      修改成功的商品种类的数量(不是每一件商品的数量总和，也不是商品类别的数量，其实就是t_goods表中受影响的行数)
     */
    @Override
    public int alter(Goods goods, Goods desti, boolean useLike) {
        //判空，goods允许为空，goods为空则进行全表更新
        if(desti == null) return 0;

        ArgsList<Object> args = new ArgsList<>();
        StringBuilder sql_set = new StringBuilder();

        boolean firstArg = true;
        String sql = "update t_goods set";

        if(!Common.isStringEmpty(desti.getG_name()))
        {
            sql_set.append(" g_name = ?");
            args.add(desti.getG_name());
            firstArg = false;
        }

        if(desti.getSt_id() != null)
        {
            if(!firstArg) sql_set.append(',');
            sql_set.append(" st_id = ?");
            args.add(desti.getSt_id());
            firstArg = false;
        }

        if(desti.getG_price() != null)
        {
            if(!firstArg) sql_set.append(',');
            sql_set.append(" g_price = ?");
            args.add(desti.getG_price());
            firstArg = false;
        }

        if(desti.getG_vip_price() != null)
        {
            if(!firstArg) sql_set.append(',');
            sql_set.append(" g_vip_price = ?");
            args.add(desti.getG_vip_price());
            firstArg = false;
        }

        if(!Common.isStringEmpty(desti.getG_descript()))
        {
            if(!firstArg) sql_set.append(',');
            sql_set.append(" g_descript = ?");
            args.add(desti.getG_descript());
            firstArg = false;
        }

        if(!Common.isStringEmpty(desti.getG_pic_address()))
        {
            if(!firstArg) sql_set.append(',');
            sql_set.append(" g_pic_address = ?");
            args.add(desti.getG_pic_address());
            firstArg = false;
        }

        if(!Common.isStringEmpty(desti.getG_barcode()))
        {
            if(!firstArg) sql_set.append(',');
            sql_set.append(" g_barcode = ?");
            args.add(desti.getG_barcode());
            firstArg = false;
        }

        if(desti.getG_count() != null)
        {
            if(!firstArg) sql_set.append(',');
            sql_set.append(" g_count = ?");
            args.add(desti.getG_count());
            firstArg = false;
        }

        if(desti.getG_slife() != null)
        {
            if(!firstArg) sql_set.append(',');
            sql_set.append(" g_slife = ?");
            args.add(desti.getG_slife());
            firstArg = false;
        }

        if(desti.getG_score() != null)
        {
            if(!firstArg) sql_set.append(',');
            sql_set.append(" g_score = ?");
            args.add(desti.getG_score());
            firstArg = false;
        }

        if(!Common.isStringEmpty(desti.getG_status()))
        {
            if(!firstArg) sql_set.append(',');
            sql_set.append(" g_status = ?");
            args.add(desti.getG_status());
        }

        sql += sql_set.toString() + makeWhereCondition(args, goods, false, 0, false, 0, 0, useLike);

        int count = 0;
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            count = conn.update(args, sql);
            JDBCFactory.returnBack(conn);
            return count;
        } catch(SQLException e) {
            System.err.println(e.getMessage());
            return 0;
        }
    }

    /**
     * 查询商品信息
     * @param g        包含要查找的商品信息的对象，null字段为任意匹配，直接设为null即为全部查询
     * @param sorting  是否排序
     * @param orderCol 排序的列
     * @param desc     降序排序
     * @param pageSize 分页查询 —— 每页最大记录条数，若设为0则不分页，将进行全表查询
     * @param page     分页查询 —— 当前页码，若设为0则不分页，将进行全表查询
     * @return         包含商品详细信息查询结果的列表
     */
    @Override
    public List<Goods> query(Goods g, boolean sorting, int orderCol, boolean desc, int pageSize, int page, boolean useLike) {
        List<Object> args  = new ArgsList<>();
        String sql = "select * from t_goods" + makeWhereCondition(args, g, sorting, orderCol, desc, pageSize, page, useLike);
        List<Goods> result = null;

        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            result = getResultList(conn.query(args, sql.toString()));
            JDBCFactory.returnBack(conn);
            return result;
        } catch(SQLException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    /**
     * 包装并返回查询到的对象的列表
     * @param list 包含 SQL 行查询结果的列表，Object[]中每一项都是一列的值
     * @return 返回包装好的对象列表
     */
    private static List<Goods> getResultList(List<Object[]> list)
    {
        List<Goods> result = new ResultList<>();
        for(Object[] row : list) result.add(new Goods(row));
        return result;
    }

    /**
     * 按照包含要查找的商品信息的对象生成sql查询字符串where子句并填充 ? 对应的实参列表
     * @param args     要填充的实参列表
     * @param g        包含要查找的商品信息的对象，null字段为任意匹配，直接设为null即为全部查询
     * @param sorting  是否排序
     * @param orderCol 排序的列
     * @param desc     降序排序
     * @param pageSize 分页查询 —— 每页最大记录条数，若设为0则不分页，将获得全表查询的sql字符串
     * @param page     分页查询 —— 当前页码，若设为0则不分页，将获得全表查询的sql字符串
     * @return         sql查询字符串where子句，若分页，则包含limit子句
     */
    private String makeWhereCondition
    (List<Object> args, Goods g, boolean sorting, int orderCol, boolean desc, int pageSize, int page, boolean useLike) {
        StringBuilder sql = new StringBuilder();

        boolean firstArg = true;


        if(useLike) switch(0){ default:
            if(g.getG_id() != null){
                sql.append(" where g_id like ?");
                args.add(g.getG_id());
                break;
            }

            if(!Common.isStringEmpty(g.getG_barcode())){
                sql.append(" where g_barcode like ?");
                args.add(g.getG_barcode());
                break;
            }
            //---------------------以上是唯一字段的查找-----------------------
            if(!Common.isStringEmpty(g.getG_name())){
                sql.append(" where g_name like ?");
                args.add(g.getG_name());
                firstArg = false;
            }

            if(g.getSt_id() != null){
                if(firstArg) sql.append(" where"); else sql.append(" or");
                sql.append(" st_id like ?");
                args.add(g.getSt_id());
                firstArg = false;
            }

            if(g.getG_price() != null){
                if(firstArg) sql.append(" where"); else sql.append(" or");
                sql.append(" g_price like ?");
                args.add(g.getG_price());
                firstArg = false;
            }

            if(g.getG_vip_price() != null){
                if(firstArg) sql.append(" where"); else sql.append(" or");
                sql.append(" g_vip_price like ?");
                args.add(g.getG_vip_price());
                firstArg = false;
            }

            if(!Common.isStringEmpty(g.getG_descript())){
                if(firstArg) sql.append(" where"); else sql.append(" or");
                sql.append(" g_descript like ?");
                args.add(g.getG_descript());
                firstArg = false;
            }

            if(!Common.isStringEmpty(g.getG_pic_address())){
                if(firstArg) sql.append(" where"); else sql.append(" or");
                sql.append(" g_pic_address like ?");
                args.add(g.getG_pic_address());
                firstArg = false;
            }

            if(g.getG_count() != null){
                if(firstArg) sql.append(" where"); else sql.append(" or");
                sql.append(" g_count like ?");
                args.add(g.getG_count());
                firstArg = false;
            }

            if(g.getG_slife() != null){
                if(firstArg) sql.append(" where"); else sql.append(" or");
                sql.append(" g_slife like ?");
                args.add(g.getG_slife());
                firstArg = false;
            }

            if(g.getG_score() != null){
                if(firstArg) sql.append(" where"); else sql.append(" or");
                sql.append(" g_score like ?");
                args.add(g.getG_score());
                firstArg = false;
            }

            if(!Common.isStringEmpty(g.getG_status())){
                if(firstArg) sql.append(" where"); else sql.append(" or");
                sql.append(" g_status like ?");
                args.add(g.getG_status());
            }
        } else switch(0) { default:
            if(g.getG_id() != null){
                sql.append(" where g_id = ?");
                args.add(g.getG_id());
                break;
            }

            if(!Common.isStringEmpty(g.getG_barcode())){
                sql.append(" where g_barcode = ?");
                args.add(g.getG_barcode());
                break;
            }
            //---------------------以上是唯一字段的查找-----------------------
            if(!Common.isStringEmpty(g.getG_name())){
                sql.append(" where g_name = ?");
                args.add(g.getG_name());
                firstArg = false;
            }

            if(g.getSt_id() != null){
                if(firstArg) sql.append(" where"); else sql.append(" or");
                sql.append(" st_id = ?");
                args.add(g.getSt_id());
                firstArg = false;
            }

            if(g.getG_price() != null){
                if(firstArg) sql.append(" where"); else sql.append(" and");
                sql.append(" g_price = ?");
                args.add(g.getG_price());
                firstArg = false;
            }

            if(g.getG_vip_price() != null){
                if(firstArg) sql.append(" where"); else sql.append(" and");
                sql.append(" g_vip_price = ?");
                args.add(g.getG_vip_price());
                firstArg = false;
            }

            if(!Common.isStringEmpty(g.getG_descript())){
                if(firstArg) sql.append(" where"); else sql.append(" and");
                sql.append(" g_descript = ?");
                args.add(g.getG_descript());
                firstArg = false;
            }

            if(!Common.isStringEmpty(g.getG_pic_address())){
                if(firstArg) sql.append(" where"); else sql.append(" and");
                sql.append(" g_pic_address = ?");
                args.add(g.getG_pic_address());
                firstArg = false;
            }

            if(g.getG_count() != null){
                if(firstArg) sql.append(" where"); else sql.append(" and");
                sql.append(" g_count = ?");
                args.add(g.getG_count());
                firstArg = false;
            }

            if(g.getG_slife() != null){
                if(firstArg) sql.append(" where"); else sql.append(" and");
                sql.append(" g_slife = ?");
                args.add(g.getG_slife());
                firstArg = false;
            }

            if(g.getG_score() != null){
                if(firstArg) sql.append(" where"); else sql.append(" and");
                sql.append(" g_score = ?");
                args.add(g.getG_score());
                firstArg = false;
            }

            if(!Common.isStringEmpty(g.getG_status())){
                if(firstArg) sql.append(" where"); else sql.append(" and");
                sql.append(" g_status = ?");
                args.add(g.getG_status());
            }
        }

        if(sorting) {
            sql.append(" order by ");
            sql.append(orderCol);
            sql.append(desc? " asc": " desc");
        }

        if(pageSize > 0  &&  page > 0) {
            sql.append(" limit ?, ?");
            args.add((page - 1) * pageSize);
            args.add(pageSize);
        }

        return sql.toString();
    }

    @Override
    public List<Goods> query(Goods g, int pageSize, int page) {
        return query(g, true, 1, true, pageSize, page, true);
    }

    @Override
    public List<Goods> query(Goods goods) {
        return query(goods, 0, 0);
    }
    @Override
    public List<Goods> query(int pageSize, int page) {
        return query(null, pageSize, page);
    }
    @Override
    public List<Goods> query() {
        return query(null);
    }
    @Override
    public List<Goods> queryALL() {
        return query();
    }
    @Override
    public List<Goods> queryALL(int pageSize, int page) {
        return query(pageSize, page);
    }


}
